#include <iostream>
#include <string>
#include <sstream>
#include <stdexcept>

extern "C" {
#include <neo4j-client.h>
}

void query_test(){

    // 2. --- 建立连接 ---
    const char* uri = "bolt://neo4j:213007@localhost:7687";
    neo4j_connection_t* connection = nullptr;
    neo4j_result_stream_t* stream = nullptr;

    try {
        // 连接到 Neo4j 数据库
        // NEO4J_INSECURE 用于禁用 TLS（测试环境），生产环境应使用安全连接
        connection = neo4j_connect(uri, nullptr, NEO4J_INSECURE);
        if (connection == nullptr) {
            std::ostringstream oss;
            oss << "Failed to connect to Neo4j: errno=" << errno << " (" << strerror(errno) << ")";
            throw std::runtime_error(oss.str());
        }
        std::cout << "Successfully connected to Neo4j at " << uri << std::endl;

        std::ostringstream cypher_oss;
        // cypher_oss << "MATCH (origin_list:List {id: 201}) "
        //             << "RETURN origin_list AS node, NULL AS rel";
        // cypher_oss << "MATCH (user:User {id: 101})-[r]->(list) "
        //             << "RETURN user AS node, r, list";
        cypher_oss << "MATCH (parent_node {id: 101})-[r]->(son_node) "
           << "RETURN parent_node, r, son_node";
        const std::string cypher_query = cypher_oss.str();
        neo4j_value_t params =  neo4j_null; // 这里我们没有实际的参数，但为了演示，可以添加一个

        std::cout << "Executing Cypher Query:\n" << cypher_query << std::endl;

        // 执行查询
        stream = neo4j_run(connection, cypher_query.c_str(), params);
        if (stream == nullptr) {
            std::ostringstream oss;
            oss << "neo4j_run() failed: errno=" << errno << " (" << strerror(errno) << ")";
            throw std::runtime_error(oss.str());
        }

        // 4. --- 解析并打印结果流 ---
        std::cout << "\n--- Printing Result Stream Data ---" << std::endl;

        neo4j_result_t* result;
        int row_count = 0;
        while ((result = neo4j_fetch_next(stream)) != nullptr) {
            std::cout << "Row " << ++row_count << ":" << std::endl;

            // 获取当前行的字段数量
            unsigned int nfields = neo4j_nfields(stream);
            for (unsigned int i = 0; i < nfields; ++i) {
                // 获取字段名
                const char* field_name_cstr = neo4j_fieldname(stream, i);
                std::string field_name = field_name_cstr ? field_name_cstr : "unnamed_field_" + std::to_string(i);

                // 获取字段值
                neo4j_value_t field_value = neo4j_result_field(result, i);

                // 检查字段值是否为 NULL
                if (neo4j_is_null(field_value)) {
                    std::cout << "  Field '" << field_name << "': NULL" << std::endl;
                    continue;
                }

                // 获取字段值的类型
                neo4j_type_t value_type = neo4j_type(field_value);

                // 根据类型打印字段值
                char buffer[4096];
                neo4j_tostring(field_value, buffer, sizeof(buffer));
                ssize_t len = strlen(buffer);

                if (len >= 0) {
                    std::cout << "  Field '" << field_name << "' (Type: " << neo4j_typestr(value_type);
                    std::cout << "): " << std::string(buffer, len) << std::endl;
                } else {
                    std::cout << "  Field '" << field_name << "': Failed to convert to string." << std::endl;
                }
            }
            std::cout << "---" << std::endl;
        }

        if (row_count == 0) {
            std::cout << "No results returned from the query." << std::endl;
        } else {
            std::cout << "Total " << row_count << " row(s) returned." << std::endl;
        }

    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    } catch (...) {
        std::cerr << "Unknown error occurred." << std::endl;
    }

    // 5. --- 清理资源 ---
    if (stream != nullptr) {
        neo4j_close_results(stream);
    }
    if (connection != nullptr) {
        neo4j_close(connection);
    }
    std::cout << "Program finished." << std::endl;

}

int main() {
    // query_test();
    // 初始化Neo4j客户端库
    if (neo4j_client_init() != 0) {
        std::cerr << "Failed to initialize Neo4j client" << std::endl;
        return 1;
    }

    try {
        // 数据库连接信息
        const char* uri = "bolt://neo4j:213007@localhost:7687";  // 根据实际情况修改

        // 建立连接
        std::cout << "Connecting to Neo4j database..." << std::endl;
        neo4j_connection_t* connection = neo4j_connect(uri, nullptr, NEO4J_INSECURE);

        std::cout << "Connected successfully!" << std::endl;

        // 构造Cypher查询
        std::ostringstream cypher_oss;
        cypher_oss << "MATCH (parent_node)-[r]->(son_node) "
                   << "RETURN parent_node, r, son_node";
        
        std::string cypher = cypher_oss.str();
        std::cout << "Executing Cypher: " << cypher << std::endl;

        // 执行查询
        neo4j_result_stream_t* results = neo4j_run(connection, cypher.c_str(), neo4j_null);

        // 获取列数
        unsigned int ncolumns = neo4j_nfields(results);
        std::cout << "Number of columns: " << ncolumns << std::endl;

        // 打印列名
        std::cout << "Columns: ";
        for (unsigned int i = 0; i < ncolumns; i++) {
            std::cout << "'" << neo4j_fieldname(results, i) << "'";
            if (i < ncolumns - 1) std::cout << ", ";
        }
        std::cout << std::endl;

        // 处理结果流
        neo4j_result_t* result;
        int row_count = 0;
        
        while ((result = neo4j_fetch_next(results)) != nullptr) {
            row_count++;
            std::cout << "\n--- Row " << row_count << " ---" << std::endl;
            
            // 遍历每一列
            for (unsigned int i = 0; i < ncolumns; i++) {
                const char* field_name = neo4j_fieldname(results, i);
                neo4j_value_t value = neo4j_result_field(result, i);
                
                // 将值转换为字符串
                char value_str[1024];
                neo4j_tostring(value, value_str, sizeof(value_str));
                std::cout << field_name << ": " << value_str << std::endl;
            }
        }
        neo4j_close_results(results);
        neo4j_close(connection);

    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        neo4j_client_cleanup();
        return 1;
    }

    // 清理客户端库
    neo4j_client_cleanup();
    std::cout << "Disconnected from Neo4j database." << std::endl;

    return 0;
}